#region license
# This file is part of Grawlix.
# 
# Grawlix is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
# 
# Grawlix is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public
# License along with Grawlix.  If not, see
# <http://www.gnu.org/licenses/>.
#endregion

"""Automatic log4net logging compile-time macro syntax."""

namespace Grawlix.Meta
import System
import Boo.Lang.Compiler

macro log:
"""
Log some text to a log bound to the current type.
Remarks: Using this macro will make the compilation unit dependent on log4net.
"""
	#markNamespaceUsed(enclosingModule(log),	"Grawlix.Meta")
	validLevels = ["Debug", "Info", "Warn", "Error", "Fatal"]
	syntaxOK = false
	if log.Arguments.Count == 1:
		level = "Info"
		message = log.Arguments[0]
		syntaxOK = true
	elif log.Arguments.Count == 2:
		if log.Arguments[0].NodeType == Ast.NodeType.ReferenceExpression:
			levelRef = log.Arguments[0] as Ast.ReferenceExpression
			level = levelRef.Name
			if validLevels.Contains(level):
				message = log.Arguments[1]
				syntaxOK = true
	if not syntaxOK:
		raise ArgumentException(
			"The log macro was used with invalid syntax. " +
			"It should be used in form log \"Message\" or " +
			"log Level, \"Message\", " +
			"where Level is one of " + join(validLevels, ", ") + " " +
			"and \"Message\" is the log message string.")
	if log.Block.HasStatements:
		raise ArgumentException(
			"The log macro does not use block notation. " +
			"It should be used in form log \"Message\" or " +
			"log Level, \"Message\", " +
			"where Level is one of " + join(validLevels, ", ") + " " +
			"and \"Message\" is the log message string.")
	type = enclosingType(log)
	typeName = type.FullName
	identifier = \
		Ast.AstUtil.BuildUniqueTypeMemberName(type, 'log')
	exists = false
	for member in type.Members:
		if member.Name == identifier:
			exists = true
			break
	if not exists:
		logNode = [|
			private static $identifier = (
				log4net.LogManager.GetLogger($typeName))
		|]
		logNode.LexicalInfo = log.LexicalInfo
		type.Members.Add(logNode)
	logReference = Ast.ReferenceExpression(identifier)
	levelEnabled = "Is${level}Enabled"
	return [|
		if self.$logReference.$levelEnabled:
			self.$logReference.$level($message)
	|]
